home *** CD-ROM | disk | FTP | other *** search
/ C/C++ 3D Game Tools / C-C++ 3D Game Tools.iso / ziptools / arj / lzhspl.arj / LHASPLIT.CPP next >
Encoding:
C/C++ Source or Header  |  1992-09-08  |  8.9 KB  |  390 lines

  1. // LZH file spliter. Uses best fit approach in C++. By Bill Ataras.
  2. //
  3. // This code is hereby public domain.
  4. //
  5. // I am an ASP member. I have two other products:
  6. //
  7. //   1. DFL (Duplicate File Locator). Does everything. Archives, CRCs,
  8. //      system security scanning.
  9. //   2. PowerInstall. Excellent installation utility. Runs in 5 languages:
  10. //      English, French, German, Italian and Spanish. A 6th, user-definable
  11. //      language is available too. Also converts self-extracting archives to
  12. //      self-extracting-installing archives with a windowed interface.
  13. //      Both the installation and the self-extractor-installer interface can
  14. //      auto-detect the customer's Dos country code and interface with him in
  15. //      the proper language. This utility is used by Hewlett-Packard for
  16. //      international distribution of Autocad plotter drivers. Also used by
  17. //      Delta Airlines.
  18. //
  19. // For a fully-functional shareware copy of either of these programs, send $5
  20. // ($10 outside North America) per program to:
  21. //
  22. //   William S. Ataras III
  23. //   1125 Balclutha Dr. #K108
  24. //   Foster City, Ca. 94404
  25. //
  26. //   Compuserve address: 70400,3542
  27. //
  28. // Thank you.
  29. //
  30.  
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <io.h>
  35. #include <fcntl.h>
  36. #include <conio.h>
  37. #include <string.h>
  38. #include <share.h>
  39. #include <sys\stat.h>
  40.  
  41.  
  42. /*****************************************************************************
  43.  
  44.                                    Defines
  45.  
  46. *****************************************************************************/
  47.  
  48. #define  BUFLEN  0x8000
  49. #define  TRUE    1
  50. #define  FALSE   0
  51.  
  52.  
  53. /*****************************************************************************
  54.  
  55.                                  Prototypes
  56.  
  57. *****************************************************************************/
  58.  
  59.  
  60. /*****************************************************************************
  61.  
  62.                             Data and variables
  63.  
  64. *****************************************************************************/
  65.  
  66. struct HEADER1
  67. {
  68.   int   garbage1;
  69.   char  garbage2 [ 5 ];
  70.   long  CompLen;
  71.   long  garbage3;
  72.   char  garbage4 [ 6 ];
  73.   char  NameLen;
  74. };
  75.  
  76. struct HEADER2
  77. {
  78.   char  garbage1 [ 5 ];
  79. };
  80.  
  81. struct LZHCHILD
  82. {
  83.   long      StartPos;
  84.   int       Handle, Opened;
  85.  
  86. public:
  87.  
  88.   LZHCHILD  *Next;
  89.   long      TotLen;
  90.   int       IsUsed;
  91.  
  92.   LZHCHILD ( int );
  93.  
  94.   void  Copy ( int );
  95. };
  96.  
  97.  
  98. class LZHFILE
  99.  
  100. {
  101.   LZHCHILD  *First;
  102.   long      ThisLen;
  103.   int       Handle,
  104.             Reading;
  105.   char      *Name;
  106.  
  107. public:
  108.  
  109.   int  Opened;
  110.  
  111.   LZHFILE  ( char *, int );                         // Open and read LZH file
  112.   ~LZHFILE ();                                      // Close LZH file
  113.  
  114.   long      Length  () {return(ThisLen);};          // Get current filelength
  115.   LZHCHILD  *FindLE ( long );                       // Next file <=
  116.   int       AnyGE   ( long Len )
  117.     {if(First&&First->TotLen>=Len)                  // Any files >= length ?
  118.      return(1);return(0);};
  119.   void      Add     ( LZHCHILD * );                 // Write given file
  120.   int       AnyLeft ();                             // Any files left ?
  121. };
  122.  
  123. char  *Buffer = NULL;
  124.  
  125. /*****************************************************************************
  126.  
  127.                                    CODE !
  128.  
  129. *****************************************************************************/
  130.  
  131.  
  132. /*****************************************************************************
  133.  
  134. Function    : main
  135.  
  136. Description : Main routine for LZH file spliter.
  137.  
  138. Parameters  : Command line:
  139.  
  140.                 LZH filename.
  141.                 Size to split into.
  142.  
  143. Returns     : Nothing.
  144.  
  145. *****************************************************************************/
  146.  
  147. void  main ( int argc, char **argv )
  148.  
  149. {
  150.   if ( argc < 3 )
  151.     {
  152.       puts ( "Usage: LZHSPLIT lzhfile fitlength" );
  153.       puts ( "By:    Bill Ataras"                );
  154.       puts ( "CIS:   70400,3542"                 );
  155.       return;
  156.     }
  157.  
  158.   Buffer = (char*)malloc ( BUFLEN );
  159.  
  160.   char  Newfile [ 128 ];
  161.   char  *ch;
  162.  
  163.   strcpy ( Newfile, argv [ 1 ] );
  164.   ch = strrchr ( Newfile, '.' );
  165.  
  166.   if ( !ch || strchr ( ch, '\\' ) ) strcat ( Newfile, ".LZH" );
  167.  
  168.   LZHFILE  *Infile = new LZHFILE ( Newfile, 0 );             // Open for read
  169.  
  170.   if ( !Infile || !Buffer )
  171.     {
  172.       puts ( "Out of memory");
  173.       return;
  174.     }
  175.  
  176.   if ( !Infile->Opened )
  177.     {
  178.       delete Infile;
  179.       printf ( "Can't open %s\n", Newfile );
  180.       return;
  181.     }
  182.  
  183.   char      Outname [ 13 ];
  184.   int       Outcnt = 1;
  185.   long      Outlen = atol ( argv [ 2 ] );
  186.   LZHCHILD  *File = NULL;
  187.  
  188.   if ( Infile->AnyGE ( Outlen ) )
  189.     {
  190.       delete Infile;
  191.       printf ( "There is a file in %s that is bigger than %ld\n",
  192.                Newfile, Outlen );
  193.       return;
  194.     }
  195.  
  196.   while ( Infile->AnyLeft () )
  197.     {
  198.       sprintf ( Outname, "SPLIT%03d.LZH", Outcnt++ );
  199.  
  200.       LZHFILE  *Outfile = new LZHFILE ( Outname, 1 );     // Create for write
  201.  
  202.       if ( !Outfile->Opened )
  203.         {
  204.           printf ( "Can't open %s\n", Outname );
  205.           break;
  206.         }
  207.  
  208.       printf ( "Writing %s -> ", Outname );
  209.  
  210.       while ( Outlen > Outfile->Length () &&                  // Bytes left ?
  211.               NULL != ( File = Infile->FindLE (Outlen-Outfile->Length()) ) )
  212.         Outfile->Add   ( File );                                  // Add file
  213.  
  214.       if ( Outfile->Length() > 1 )
  215.         printf ( "%6ld bytes\n", Outfile->Length() );
  216.       else
  217.         printf ( "\r                          " );
  218.  
  219.       delete Outfile;                                  // Done with this file
  220.     }
  221.  
  222.   delete Infile;
  223.  
  224.   puts ( "Done." );
  225. }
  226.  
  227. LZHCHILD::LZHCHILD ( int Fl )
  228.  
  229. {
  230.   HEADER1  h1;
  231.   HEADER2  h2;
  232.  
  233.   Handle   = Fl;
  234.   Opened   = FALSE;
  235.   StartPos = tell ( Fl );
  236.  
  237.   if ( read ( Fl, &h1, sizeof ( h1 ) ) != sizeof ( h1 ) ) return;
  238.   lseek ( Fl, h1.NameLen, SEEK_CUR );
  239.   if ( read ( Fl, &h2, sizeof ( h2 ) ) != sizeof ( h2 ) ) return;
  240.  
  241.   lseek ( Fl, h1.CompLen, SEEK_CUR );                       // Skip file data
  242.  
  243.   TotLen  = h1.CompLen + sizeof ( h1 ) + sizeof ( h2 ) + h1.NameLen;
  244.   Next    = NULL;
  245.   Opened  = TRUE;
  246.   IsUsed  = FALSE;
  247. }
  248.  
  249. void  LZHCHILD::Copy ( int Fl )
  250.  
  251. {
  252.   lseek ( Handle, StartPos, SEEK_SET );
  253.  
  254.   long  Tot = 0L;
  255.  
  256.   while ( Tot < TotLen )
  257.     {
  258.       unsigned Len = read ( Handle, Buffer, (long)BUFLEN<TotLen-Tot?BUFLEN:TotLen-Tot );
  259.       write ( Fl, Buffer, Len );
  260.       Tot += Len;
  261.     }
  262.  
  263.   IsUsed = TRUE;
  264. }
  265.  
  266.  
  267. LZHFILE::LZHFILE ( char *File, int Create )
  268.  
  269. {
  270.   if ( Create )
  271.     Handle = sopen ( File, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, SH_DENYWR, S_IWRITE );
  272.   else
  273.     Handle = sopen ( File, O_BINARY|O_RDONLY, SH_DENYWR, S_IREAD );
  274.  
  275.   if ( Handle < 0 )
  276.     {
  277.       Opened = FALSE;
  278.       return;
  279.     }
  280.  
  281.   Name = strdup ( File );                                        // Save name
  282.  
  283.   Reading = !Create;
  284.   Opened  = TRUE;
  285.   First   = NULL;
  286.   ThisLen = Reading ? 0L : filelength ( Handle );
  287.  
  288.   if ( !Reading ) return;
  289.  
  290.   First = new LZHCHILD ( Handle );
  291.  
  292.   if ( !First || !First->Opened )
  293.     {
  294.       Opened = FALSE;
  295.       return;
  296.     }
  297.  
  298.   while ( TRUE )                                             // Read LZH file
  299.     {
  300.       LZHCHILD  *Child = new LZHCHILD ( Handle );
  301.  
  302.       if ( !Child || !Child->Opened ) break;
  303.  
  304.       LZHCHILD *Find, *Prev = NULL;
  305.  
  306.       for ( Find = First; Find; Find = Find->Next )
  307.         {
  308.           if ( Child->TotLen > Find->TotLen )      // Add in descending order
  309.             if ( Prev )
  310.               {
  311.                 Prev->Next  = Child;
  312.                 Child->Next = Find;
  313.                 break;
  314.               }
  315.             else
  316.               {
  317.                 Child->Next = First;
  318.                 First       = Child;
  319.                 break;
  320.               }
  321.  
  322.           Prev = Find;
  323.         }
  324.  
  325.       if ( !Find ) Prev->Next = Child;
  326.     }
  327. }
  328.  
  329. LZHFILE::~LZHFILE ()
  330.  
  331. {
  332.   if ( Reading )
  333.     {
  334.       LZHCHILD  *Child, *Tmp;
  335.  
  336.       for ( Child = First; Child; )                          // Kill Children
  337.         {
  338.           Tmp = Child;
  339.           Child = Child->Next;
  340.           delete Tmp;
  341.         }
  342.  
  343.       close ( Handle );
  344.       return;
  345.     }
  346.  
  347.   if ( Length () )
  348.     {
  349.       lseek ( Handle, 0L, SEEK_END );
  350.       char  End = 0;
  351.       write ( Handle, &End, 1 );
  352.       close ( Handle );
  353.       return;
  354.     }
  355.  
  356.   close ( Handle );
  357.   unlink ( Name );
  358. }
  359.  
  360. LZHCHILD  *LZHFILE::FindLE ( long Len )
  361.  
  362. {
  363.   LZHCHILD  *Find;
  364.  
  365.   for ( Find = First;
  366.         Find && ( Find->TotLen > Len || Find->IsUsed );
  367.         Find = Find->Next );
  368.  
  369.   return ( Find );
  370. }
  371.  
  372. void  LZHFILE::Add ( LZHCHILD *Child )
  373.  
  374. {
  375.   if ( Reading ) return;
  376.  
  377.   Child->Copy ( Handle );
  378.   ThisLen = filelength ( Handle ) + 1;
  379. }
  380.  
  381. int  LZHFILE::AnyLeft ()
  382.  
  383. {
  384.   LZHCHILD  *Find;
  385.  
  386.   for ( Find = First; Find && Find->IsUsed; Find = Find->Next );
  387.  
  388.   return ( !(Find == NULL) );
  389. }
  390.